import json
import logging
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.hashers import check_password, make_password

from Server.models import User
from Server.forms import LoginForm
from Server.enum import CommonSuccessCode, CommonErrorCode, UserBackCode
from Server.sms_service import SMSService, SMSCodeType

logger = logging.getLogger(__name__)


@csrf_exempt
def auth_login(request):
    """
    用户登录接口：支持 application/json 或表单提交
    请求参数：phone, password
    响应：
      - 成功：code=200, data=用户基本信息（不包含密码）
      - 失败：对应错误码
    """
    if request.method == "POST":
        # 兼容 JSON 与表单
        if request.content_type and "application/json" in request.content_type:
            try:
                data = json.loads(request.body)
            except Exception:
                return JsonResponse({"code": CommonErrorCode.form_not_valid.value, "error": "JSON解析失败"})
            phone = data.get("phone")
            password = data.get("password")
        else:
            form = LoginForm(request.POST or None)
            if not form.is_valid():
                return JsonResponse({"code": CommonErrorCode.form_not_valid.value, "error": "表单校验不通过"})
            phone = form.cleaned_data["phone"]
            password = form.cleaned_data["password"]

        if not phone or not password:
            return JsonResponse({"code": CommonErrorCode.param_not_found.value, "error": "必要参数缺失或者为空"})

        user_one = User.objects.filter(phone=phone).first()
        if not user_one:
            return JsonResponse({"code": UserBackCode.unregistered_user.value, "error": "用户未注册"})

        def build_back_user(u: User):
            return {
                "id": u.id,
                "phone": u.phone,
                "username": u.username,
                "head_portrait": u.head_portrait.url if u.head_portrait else "",
                "money": u.money,
                "is_admin": u.is_admin
            }

        # 优先校验哈希密码
        if check_password(password, user_one.password):
            return JsonResponse({"code": CommonSuccessCode.success.value, "msg": "登录成功", "data": build_back_user(user_one)})
        # 兼容历史明文口令：若数据库仍为明文且相等，则自动迁移为哈希并登录
        if user_one.password == password:
            user_one.password = make_password(password)
            user_one.save(update_fields=["password"])
            return JsonResponse({"code": CommonSuccessCode.success.value, "msg": "登录成功", "data": build_back_user(user_one)})
        # 其他情况视为密码错误
        return JsonResponse({"code": CommonErrorCode.form_not_valid.value, "error": "密码错误"})
    else:
        return JsonResponse({"code": CommonErrorCode.method_error.value, "error": "请求方式错误"})


@csrf_exempt
def send_sms_code(request):
    """
    发送短信验证码接口
    请求参数：phone, code_type (可选，默认为register)
    code_type: register-注册, login-登录, reset-重置密码
    """
    if request.method == "POST":
        try:
            if request.content_type and "application/json" in request.content_type:
                data = json.loads(request.body)
            else:
                data = request.POST
            
            phone = data.get("phone")
            code_type = data.get("code_type", SMSCodeType.REGISTER)
            
            if not phone:
                return JsonResponse({
                    "code": CommonErrorCode.param_not_found.value,
                    "error": "手机号不能为空"
                })
            
            # 验证手机号格式
            import re
            if not re.fullmatch(r"\d{11}", phone):
                return JsonResponse({
                    "code": CommonErrorCode.form_not_valid.value,
                    "error": "手机号格式不正确"
                })
            
            # 如果是注册类型，检查手机号是否已注册
            if code_type == SMSCodeType.REGISTER:
                if User.objects.filter(phone=phone).exists():
                    return JsonResponse({
                        "code": UserBackCode.registered_user.value,
                        "error": "该手机号已注册"
                    })
            
            # 如果是登录或重置密码，检查手机号是否存在
            if code_type in [SMSCodeType.LOGIN, SMSCodeType.RESET_PASSWORD]:
                if not User.objects.filter(phone=phone).exists():
                    return JsonResponse({
                        "code": UserBackCode.unregistered_user.value,
                        "error": "该手机号未注册"
                    })
            
            # 发送验证码
            success, message, code = SMSService.send_code(phone, code_type)
            
            if success:
                logger.info(f'验证码发送成功: {phone} -> {code}')
                # 开发环境返回验证码（方便测试），生产环境不应返回
                return JsonResponse({
                    "code": CommonSuccessCode.success.value,
                    "msg": message,
                    "data": {
                        "phone": phone,
                        "code": code,  # 仅开发环境
                        "expire_time": 300  # 有效期（秒）
                    }
                })
            else:
                return JsonResponse({
                    "code": CommonErrorCode.server_error.value,
                    "error": message
                })
        
        except Exception as e:
            logger.exception(f'发送验证码失败: {str(e)}')
            return JsonResponse({
                "code": CommonErrorCode.server_error.value,
                "error": f"发送失败: {str(e)}"
            })
    else:
        return JsonResponse({
            "code": CommonErrorCode.method_error.value,
            "error": "请求方式错误"
        })


@csrf_exempt
def verify_sms_code(request):
    """
    验证短信验证码接口（可选，注册时也可以直接验证）
    请求参数：phone, code, code_type (可选)
    """
    if request.method == "POST":
        try:
            if request.content_type and "application/json" in request.content_type:
                data = json.loads(request.body)
            else:
                data = request.POST
            
            phone = data.get("phone")
            code = data.get("code")
            code_type = data.get("code_type", SMSCodeType.REGISTER)
            
            if not phone or not code:
                return JsonResponse({
                    "code": CommonErrorCode.param_not_found.value,
                    "error": "手机号或验证码不能为空"
                })
            
            # 验证验证码
            success, message = SMSService.verify_code(phone, code, code_type)
            
            if success:
                return JsonResponse({
                    "code": CommonSuccessCode.success.value,
                    "msg": message
                })
            else:
                return JsonResponse({
                    "code": CommonErrorCode.form_not_valid.value,
                    "error": message
                })
        
        except Exception as e:
            logger.exception(f'验证验证码失败: {str(e)}')
            return JsonResponse({
                "code": CommonErrorCode.server_error.value,
                "error": f"验证失败: {str(e)}"
            })
    else:
        return JsonResponse({
            "code": CommonErrorCode.method_error.value,
            "error": "请求方式错误"
        })


@csrf_exempt
def login_with_code(request):
    """
    验证码登录接口
    请求参数：phone, code
    """
    if request.method == "POST":
        try:
            if request.content_type and "application/json" in request.content_type:
                data = json.loads(request.body)
            else:
                data = request.POST
            
            phone = data.get("phone")
            code = data.get("code")
            
            if not phone or not code:
                return JsonResponse({
                    "code": CommonErrorCode.param_not_found.value,
                    "error": "手机号或验证码不能为空"
                })
            
            # 验证验证码
            success, message = SMSService.verify_code(phone, code, SMSCodeType.LOGIN)
            
            if not success:
                return JsonResponse({
                    "code": CommonErrorCode.form_not_valid.value,
                    "error": message
                })
            
            # 查找用户
            user_one = User.objects.filter(phone=phone).first()
            if not user_one:
                return JsonResponse({
                    "code": UserBackCode.unregistered_user.value,
                    "error": "用户未注册"
                })
            
            # 返回用户信息
            back_user = {
                "id": user_one.id,
                "phone": user_one.phone,
                "username": user_one.username,
                "head_portrait": user_one.head_portrait.url if user_one.head_portrait else "",
                "money": user_one.money,
                "is_admin": user_one.is_admin
            }
            
            logger.info(f'用户验证码登录成功: {phone}')
            return JsonResponse({
                "code": CommonSuccessCode.success.value,
                "msg": "登录成功",
                "data": back_user
            })
        
        except Exception as e:
            logger.exception(f'验证码登录失败: {str(e)}')
            return JsonResponse({
                "code": CommonErrorCode.server_error.value,
                "error": f"登录失败: {str(e)}"
            })
    else:
        return JsonResponse({
            "code": CommonErrorCode.method_error.value,
            "error": "请求方式错误"
        })